
#include "TestApp.h"


void _convMatrix( D3DXMATRIX& _dxMatrix, CLMatrix4x4 & lMatrix)
{
	lMatrix.identity();

	for ( int i=0; i<4; i++ )
	{
		for ( int j = 0; j<4; j++ )
		{
			lMatrix.m[i][j] = _dxMatrix.m[i][j];
		}
	}

}
//--------------------------------------------------------------------------------------
// Called every time the application receives a message
//--------------------------------------------------------------------------------------
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
	PAINTSTRUCT ps;
	HDC hdc;

	switch( message )
	{
	case WM_PAINT:
		hdc = BeginPaint( hWnd, &ps );
		EndPaint( hWnd, &ps );
		break;

	case WM_DESTROY:
		PostQuitMessage( 0 );
		break;

	default:
		return DefWindowProc( hWnd, message, wParam, lParam );
	}

	return 0;
}



CTestApp::CTestApp()
{
	m_hInst = NULL;
	m_hWnd = NULL;

	m_pIndexBuffer = NULL;
	m_pVertexBuffer = NULL;
	m_pRenderSystem = NULL;
}


CTestApp::~CTestApp()
{

}


void CTestApp::onEvent(MSG& msg)
{

}


bool CTestApp::updateFrame(int passedTime)
{
	Render();
	static int FPS = 0;
	static int tempFPSTime = 0;
	FPS++;
	int nowtime = GetTickCount();
	int CurFPS = 0;
	if (nowtime - tempFPSTime >= 1000)
	{
		CurFPS = FPS;
		tempFPSTime = nowtime;
		FPS = 0;
		printf("--->FPS %d\n", CurFPS);

	}


	return true;
}


bool CTestApp::init( const char* appModuleFile )
{

	GetLaborCore()->loadPlugin( L"LaborD3D10D.dll");
	m_pRenderSystem = GetLaborCore()->getRenderSystemByName(L"D3D10 Renderer");
	GetLaborCore()->setRenderSystem( m_pRenderSystem );
	if ( NULL == m_pRenderSystem )
		return 0;


	if( FAILED( InitWindow( (HINSTANCE)m_pRenderSystem->getInst(), 0 ) ) )
		return 0;

	char _appModuleFile[256]={0};
	strncpy_s(_appModuleFile,appModuleFile,256);
	for(int i = strlen(_appModuleFile) ; i >=0 ; i --)
	{
		if(_appModuleFile[i] == '/' || _appModuleFile[i] == '\\')
		{
			_appModuleFile[i + 1] = 0;
			break;
		}
	}

	string t_strTemp = _appModuleFile;
	t_strTemp = t_strTemp.substr(0, t_strTemp.length()-1);
	int t_nPos = t_strTemp.find_last_of('\\');
	string t_strResourcePath = t_strTemp.substr(0, t_nPos+1);
	wchar_t t_strResourcePathW[4096] = {0};
	Labor_LocaleToUnicode( t_strResourcePath.c_str() ,t_strResourcePathW , 4096 );

	wstring t_strShaderPath = t_strResourcePathW;

	t_strShaderPath += L"resource\\shader\\";
	m_strShaderPath = t_strShaderPath;
	m_pRenderSystem->setShaderPath( t_strShaderPath.c_str() );

	wstring t_strTexturePath = t_strResourcePathW;

	t_strTexturePath += L"resource\\texture\\";
	m_pRenderSystem->setTexturePath( t_strTexturePath.c_str() );


	if( !m_pRenderSystem->initDevice( (int)m_hWnd) )
	{
		m_pRenderSystem->cleanUpDevice();
		return 0;
	}
	initRenderData();
	return true;

}


bool CTestApp::uinit()
{

	m_pRenderSystem->cleanUpDevice();

	return true;

}

HRESULT CTestApp::InitWindow( HINSTANCE hInstance, int nCmdShow )
{
	// Register class
	WNDCLASS wcex;
	wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = WndProc;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hInstance = hInstance;
	wcex.hIcon = LoadIcon( hInstance, ( LPCTSTR )IDI_APPLICATION );
	wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
	wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
	wcex.lpszMenuName = NULL;
	wcex.lpszClassName = L"TestRender03";
	if( !RegisterClass( &wcex ) )
		return E_FAIL;

	// Create window
	m_hInst = hInstance;
	RECT rc = { 0, 0, 640, 480 };
	AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );
	m_hWnd = CreateWindow( L"TestRender03", L"TestRender03: Test Render", WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance,
		NULL );
	if( !m_hWnd )
		return E_FAIL;

	ShowWindow( m_hWnd, TRUE );

	return S_OK;
}


void CTestApp::initRenderData()
{
	m_pRenderSystem->setInputLayout( IL_PT );


	ILGpuProgram *pGpuProgram = m_pRenderSystem->createGPUProgram();
	wstring strVS, strPS;
	strVS = m_strShaderPath;
	strPS = m_strShaderPath;

	strVS += L"vertexShader.hlsl";
	strPS += L"pixelShader.hlsl";

	pGpuProgram->load( strVS.c_str(), strPS.c_str(), NULL, 0);
	m_pRenderSystem->setGPUProgram( pGpuProgram );
	HRESULT hr = S_OK;
	// Create vertex buffer


	SimpleVertex vertices[] =
	{
		{ D3DXVECTOR4( -1.0f, 1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) },
		{ D3DXVECTOR4( 1.0f, 1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) },
		{ D3DXVECTOR4( 1.0f, 1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) },
		{ D3DXVECTOR4( -1.0f, 1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) },

		{ D3DXVECTOR4( -1.0f, -1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) },
		{ D3DXVECTOR4( 1.0f, -1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) },
		{ D3DXVECTOR4( 1.0f, -1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) },
		{ D3DXVECTOR4( -1.0f, -1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) },

		{ D3DXVECTOR4( -1.0f, -1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) },
		{ D3DXVECTOR4( -1.0f, -1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) },
		{ D3DXVECTOR4( -1.0f, 1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) },
		{ D3DXVECTOR4( -1.0f, 1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) },

		{ D3DXVECTOR4( 1.0f, -1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) },
		{ D3DXVECTOR4( 1.0f, -1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) },
		{ D3DXVECTOR4( 1.0f, 1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) },
		{ D3DXVECTOR4( 1.0f, 1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) },

		{ D3DXVECTOR4( -1.0f, -1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) },
		{ D3DXVECTOR4( 1.0f, -1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) },
		{ D3DXVECTOR4( 1.0f, 1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) },
		{ D3DXVECTOR4( -1.0f, 1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) },

		{ D3DXVECTOR4( -1.0f, -1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) },
		{ D3DXVECTOR4( 1.0f, -1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) },
		{ D3DXVECTOR4( 1.0f, 1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) },
		{ D3DXVECTOR4( -1.0f, 1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) },
	};

	SimpleVertex *pVertex = NULL;
	int vertexNumber = 24;
	m_pVertexBuffer = m_pRenderSystem->createVertexBuffer( sizeof(SimpleVertex), vertexNumber, HBU_STATIC);
	pVertex = (SimpleVertex*)m_pVertexBuffer->lock( 0, vertexNumber, eHBL_WRITE_DISCARD);
	for ( int i=0; i< vertexNumber; i++ )
	{
		*pVertex = vertices[i];
		pVertex++;
	}
	m_pVertexBuffer->unlock();


	DWORD indices[] =
	{
		3,1,0,
		2,1,3,

		6,4,5,
		7,4,6,

		11,9,8,
		10,9,11,

		14,12,13,
		15,12,14,

		19,17,16,
		18,17,19,

		22,20,21,
		23,20,22
	};


	m_pIndexBuffer  = m_pRenderSystem->createIndexBuffer( IT_32BIT, 36, HBU_WRITE_ONLY);

	int *pIndex = NULL;
	pIndex = static_cast<int*>(m_pIndexBuffer->lock(0, 36*sizeof(int), eHBL_WRITE_DISCARD));

	for ( int i=0; i< 36; i++ )
	{
		*pIndex = indices[i];
		pIndex++;
	}
	m_pIndexBuffer->unlock();
	//// Set vertex buffer
	UINT stride = sizeof( SimpleVertex );
	UINT offset = 0;
	m_pRenderSystem->setVertexBuffer( 0,1, m_pVertexBuffer, &stride, &offset);
	m_pRenderSystem->setIndexBuffer( m_pIndexBuffer, IT_32BIT );
	m_pRenderSystem->setPrimitiveTopology( eL_PT_TRIANGLELIST );


	// Initialize the world matrix
	D3DXMatrixIdentity( &m_World );

	// Initialize the view matrix
	D3DXVECTOR3 Eye( 0.0f, 0.0f, -6.0f );
	D3DXVECTOR3 At( 0.0f, 0.0f, 0.0f );
	D3DXVECTOR3 Up( 0.0f, 1.0f, 0.0f );

	D3DXMatrixLookAtLH( &m_View, &Eye, &At, &Up );

	RECT rc;
	GetClientRect( m_hWnd, &rc );
	UINT width = rc.right - rc.left;
	UINT height = rc.bottom - rc.top;

	//// Initialize the projection matrix
	D3DXMatrixPerspectiveFovLH( &m_Projection, ( float )D3DX_PI * 0.25f, width / ( FLOAT )height, 0.1f, 3000.0f );

	m_pTexture = m_pRenderSystem->createTextureFromFile(L"seafloor.dds");
	m_pRenderSystem->setTexture( m_pTexture );

	//// sample state 
	sLSamplerStateDesc _sampler_desc;
	ILSamplerState *pSamplerState = m_pRenderSystem->createSamplerState( _sampler_desc );
	m_pRenderSystem->setSamplerState( 0, pSamplerState );


	pGpuProgram->commit();
	m_pRenderSystem->setWorldMatrix( (float* )&m_World );
	m_pRenderSystem->setViewMatrix( (float* )&m_View );
	m_pRenderSystem->setProMatrix( (float* )&m_Projection );

}


//--------------------------------------------------------------------------------------
// Render the frame
//--------------------------------------------------------------------------------------
void CTestApp::Render()
{
	if ( NULL == m_pRenderSystem )
		return;
	// Update our time
	static float t = 0.0f;

	static DWORD dwTimeStart = 0;
	DWORD dwTimeCur = GetTickCount();
	if( dwTimeStart == 0 )
		dwTimeStart = dwTimeCur;
	t = ( dwTimeCur - dwTimeStart ) / 1000.0f;



	//Animate the cube

	D3DXMatrixRotationY( &m_World, t );

	m_pRenderSystem->clearBackBuffer(0.0f, 0.125f, 0.3f, 1.0f);
	m_pRenderSystem->setWorldMatrix( (float* )&m_World );


	m_pRenderSystem->begin();
	UINT stride = sizeof( SimpleVertex );
	UINT offset = 0;
	m_pRenderSystem->setVertexBuffer( 0,1, m_pVertexBuffer, &stride, &offset);
	m_pRenderSystem->setIndexBuffer( m_pIndexBuffer, IT_32BIT );
	m_pRenderSystem->setPrimitiveTopology( eL_PT_TRIANGLELIST );

	//for ( int i=0; i<1000; i++ )
		m_pRenderSystem->drawIndexed( 36, 0, 0 );
	m_pRenderSystem->present(0, 0);
	m_pRenderSystem->end();
}
